package generation;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;

import ec.EvolutionState;
import ec.Individual;
import ec.Subpopulation;
import ec.simple.SimpleStatistics;
import ec.util.Output;
import ec.util.ParameterDatabase;

public class PasswordGenerationWithMutationSimpleObjectif {
	public static String userPassword = null;
	public static ArrayList<Individual> evaluatedIndiv = new ArrayList<Individual>();
	public static final int nbrEchantillon = 5;
	public static int availableSpace = 0;

	public static void ecrireFichierPopIn(int nombreDeSouspopulation, int nombreDindividus, int tailleGenome){
		try {
			FileWriter fichier = new FileWriter("src/poptest.in",false);

			BufferedWriter output = new BufferedWriter(fichier);

			output.write("Number of Subpopulations: i" + 1 + "|\n");
			for( int i = 0; i < nombreDeSouspopulation; i++){
				output.write("Subpopulation Number: i" + i + "|\n");
				output.write("Number of Individuals: i"+ nombreDindividus + "|\n");
				for( int j = 0; j < nombreDindividus; j++){
					output.write("Individual Number: i" + j + "|\n");
					output.write("Evaluated: F" + "\n");
					output.write("Fitness: f0|0|" + "\n");
					output.write("i" + tailleGenome + "|");
					for( int k = 0; k < tailleGenome-1; k++){
						output.write("5|");
					}
					output.write("5\n");
				}
			}
			output.flush();
			output.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {

		System.out.println("Rentrer le mot de clef de base:");
		Scanner sc = new Scanner(System.in);
		userPassword = sc.nextLine();

		do {
			System.out.println("Taille maximale du mdp final ? (minimum la longueur du mot clef) ");
			availableSpace = sc.nextInt() - userPassword.length();
		}
		while(availableSpace < 0);

		ecrireFichierPopIn(1, 100, 5);

		ParameterDatabase paramDB = null;
		try {
			File parameterFile =  new File("src/transformationSimpleObjectif.params");
			paramDB = new ParameterDatabase(parameterFile, new String[] { "-file", parameterFile.getCanonicalPath() }); 
		}
		catch (IOException e) {
			System.out.println("Error: "+e);
		}

		Output out = ec.Evolve.buildOutput();

		ParameterDatabase child = new ParameterDatabase();
		child.addParent(paramDB);

		EvolutionState evaluatedState = ec.Evolve.initialize(child, 0, out);
		evaluatedState.startFresh();
		int result = EvolutionState.R_NOTDONE;
		int nbrGen = 0;
		while( result == EvolutionState.R_NOTDONE ) {
			result = evaluatedState.evolve();
			nbrGen ++;

			if(nbrGen%3 == 0) {
				Individual[] inds = ((SimpleStatistics)(evaluatedState.statistics)).getBestSoFar();
				float bestFitness = inds[0].fitness.fitness();

				evaluatedIndiv = new ArrayList<Individual>();

				Subpopulation[] subpop = evaluatedState.population.subpops;
				Individual[] indiv = subpop[0].individuals;

				ArrayList<String> indivString = new ArrayList<String>();
				ArrayList<Individual> indivArray = new ArrayList<Individual>();

				double marge = 0.01;
				while(indivString.size() < nbrEchantillon*2) {
					for(int i = 0; i < indiv.length; i++) {
						float indivFitness = indiv[i].fitness.fitness();
						if(indivFitness >= bestFitness-marge) {
							indivString.add(indiv[i].genotypeToStringForHumans());
							indivArray.add(indiv[i]);
						}
					}
					marge += 0.01;
				}

				for(int i = 0; i < nbrEchantillon; i++) {
					Random rand = new Random();
					int e = rand.nextInt(indivString.size());
					Mutation mutation = new Mutation(userPassword, availableSpace);

					System.out.println("Candidat numéro "+e+" : "+indivString.get(e));
					System.out.println("Votre mot de passe serait : "+mutation.applyMutation(indivString.get(e)));

				}
			}
		}
		ec.Evolve.cleanup(evaluatedState);
	}
}
